package com.dragon.logical.service.supplies.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dragon.common.util.DateNumUtils;
import com.dragon.logical.service.customer.CustomerService;
import com.dragon.logical.service.supplies.IProcurementService;
import com.dragon.repository.entity.*;
import com.dragon.repository.mapper.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 采购单 服务实现类
 * </p>
 *
 * @author sy
 * @since 2023-10-23
 */
@Service
public class ProcurementServiceImpl extends ServiceImpl<ProcurementMapper, Procurement> implements IProcurementService {

    @Autowired
    ProcurementMapper procurementMapper;
    @Autowired
    RequisitionProductMapper requisitionProductMapper;
    @Autowired
    ProcurementProductMapper procurementProductMapper;
    @Autowired
    PurchaseRequisitionMapper purchaseMapper;
    @Autowired
    ProductUnitMapper productUnitMapper;
    @Autowired
    WarehouseInoutMapper inoutMapper;
    @Autowired
    StockMapper stockMapper;
    @Autowired
    InoutProductMapper inoutProductMapper;
    @Autowired
    ProductMapper productMapper;
    @Autowired
    WarehouseMapper warehouseMapper;
    @Autowired
    CustomerService customerService;

    @Override
    public Page<Procurement> listProcurement(Integer page, Integer limit, Integer id, String search, Integer state, Integer procuredState) {
        Page<Procurement> procuredPage = new Page<>(page, limit);
        Page<Procurement> procurementPage = procurementMapper.selectPageByItem(procuredPage, id ,search,  state, procuredState);
        if(procurementPage == null ){
            procurementPage.setRecords(new ArrayList<Procurement>());
        } else {
            for (Procurement procurement : procurementPage.getRecords()) {
                List<ProcurementProduct> procurementProducts = procurementProductMapper.selectListByProcurementId(procurement.getId());
                procurementProducts.forEach(procurementProduct -> {
                    //String financeUnitName = productUnitMapper.getFinanceUnitName(procurementProduct.getFinanceUnitId());
                    //procurementProduct.setFinanceUnitName(financeUnitName);
                    RequisitionProduct requisitionProducts = requisitionProductMapper.selectOneDeteilById(procurementProduct.getRequisitionProductId());
                    if (requisitionProducts != null){
                        PurchaseRequisition purchaseRequisition = purchaseMapper.selectById(requisitionProducts.getRequisitionId());
                        procurementProduct.setPurchaseCode(purchaseRequisition.getPurchaseCode());
                    }
                });
                procurement.setProcurementProductList(procurementProducts);
            }
        }
        return procurementPage;
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public AddPageData addProcurement(Procurement procurement) {
        procurement.setCreateTime(DateUtil.date());
        //自动生成编号
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String code = "CG-" + sdf.format(procurement.getCreateTime());
        String maxCode =  procurementMapper.maxRoundInoutNumber(code);
        String newCode = null;
        if (StrUtil.isEmpty(maxCode)){
            newCode = code + "001";
        } else {
            String getMaxCode = maxCode.substring(11, 14);
            newCode = code + DateNumUtils.getNum(getMaxCode);
        }
        procurement.setProcuredCode(newCode);
        procurementMapper.insert(procurement);
        AtomicReference<Double> price = new AtomicReference<>(0.00);
        if (StrUtil.isBlank(procurement.getPurchaseIds())){
            procurement.getProcurementProductList().forEach(procurementProduct -> {
                //获取产品数据
                Product product = null;
                if (procurementProduct.getProductSpuId() == null){
                    product = productMapper.selectById(procurementProduct.getId());
                } else {
                    product = productMapper.selectById(procurementProduct.getProductSpuId());
                }
                procurementProduct.setId(null);
                procurementProduct.setProductSpuId(product.getId());
                procurementProduct.setProcurementId(procurement.getId());
                procurementProduct.setUnitId(product.getProductUnitId());
                procurementProduct.setProductBuyNum(procurementProduct.getFinanceBuyNum());
                procurementProduct.setProductBuyPrice(procurementProduct.getProductBuyNum() * procurementProduct.getPrice());
                procurementProductMapper.insert(procurementProduct);
                price.updateAndGet(v -> v + procurementProduct.getProductBuyPrice());
            });
            procurement.setProcuredPrice(price.get());
            procurementMapper.updateById(procurement);
        }else {
            procurement.setProcuredState(1);
            double procurementPrice = 0.00;
            for (ProcurementProduct procurementProduct : procurement.getProcurementProductList()) {
                procurementPrice += procurementProduct.getProductBuyPrice();
            }
            procurement.setProcuredPrice(procurementPrice);
            procurementMapper.updateById(procurement);
            procurement.getProcurementProductList().forEach(procurementProduct -> {
                //获取产品数据
                Product product = productMapper.selectById(procurementProduct.getProductSpuId());
                procurementProduct.setId(null);
                procurementProduct.setProcurementId(procurement.getId());
                procurementProductMapper.insert(procurementProduct);
                RequisitionProduct requisitionProduct = requisitionProductMapper.selectById(procurementProduct.getRequisitionProductId());
                requisitionProduct.setProductState(2);
                requisitionProductMapper.updateById(requisitionProduct);

            });
            List<Integer> purchaseId = Stream.of(procurement.getPurchaseIds().split(",")).map(Integer::valueOf).collect(Collectors.toList());
            purchaseId.forEach( id -> {
                PurchaseRequisition purchaseRequisition = purchaseMapper.selectById(id);
                QueryWrapper<RequisitionProduct> wrapper = new QueryWrapper<>();
                wrapper.lambda().eq(RequisitionProduct::getRequisitionId,id)
                        .eq(RequisitionProduct::getProductState,2);
                List<RequisitionProduct> requisitionProducts = requisitionProductMapper.selectList(wrapper);
                wrapper.clear();
                wrapper.lambda().eq(RequisitionProduct::getRequisitionId,id);
                List<RequisitionProduct> list = requisitionProductMapper.selectList(wrapper);
                if (requisitionProducts.size() == list.size()){
                    purchaseRequisition.setRequisitionState(2);
                }else if (requisitionProducts.size() < list.size() && requisitionProducts.size()!=0){
                    purchaseRequisition.setRequisitionState(1);
                }
                purchaseMapper.updateById(purchaseRequisition);
            });
        }


        AddPageData addPageData = new AddPageData();
        addPageData.setAdminId(procurement.getAdminId());
        addPageData.setWorkflowJson(procurement.getWorkflowJsonList());
        addPageData.setTitle(procurement.getTitle());
        addPageData.setCorrelationId(procurement.getId());
        addPageData.setStreamType(23);
        addPageData.setExempt(procurement.getExempt());
        return addPageData;
    }

    @Override
    public void updateProcurement(Procurement procurement) {
        procurement.setUpdateTime(DateUtil.date());
        AtomicReference<Double> price = new AtomicReference<>(0.00);

        if (procurement.getProcurementProductList() != null){
            procurement.getProcurementProductList().forEach(procurementProduct -> {
                //获取产品数据
                ProcurementProduct pp = procurementProductMapper.selectById(procurementProduct.getId());
//                pp.setFinanceBuyNum(procurementProduct.getFinanceBuyNum());
//                pp.setProductBuyNum(procurementProduct.getFinanceBuyNum() * pp.getConversionRate());
                pp.setProductBuyNum(procurementProduct.getFinanceBuyNum());
                pp.setFinanceBuyNum(procurementProduct.getFinanceBuyNum());
                pp.setProductBuyPrice(pp.getProductBuyNum() * pp.getPrice());
                procurementProductMapper.updateById(pp);
                price.updateAndGet(v -> v + pp.getProductBuyPrice());
            });
        }
        procurement.setProcuredPrice(price.get());
        procurementMapper.updateById(procurement);
    }

    @Override
    public void deleteById(Integer id){
        Procurement procurement = procurementMapper.selectById(id);
        if (procurement.getStatus() != 1){
            List<ProcurementProduct> procurementProducts = procurementProductMapper.selectListByProcurementId(procurement.getId());
            procurementProducts.forEach(procurementProduct -> {
                if (procurementProduct.getRequisitionProductId() != null){
                    RequisitionProduct requisitionProduct = requisitionProductMapper.selectById(procurementProduct.getRequisitionProductId());
                    requisitionProduct.setProductState(1);
                    requisitionProductMapper.updateById(requisitionProduct);
                    PurchaseRequisition purchaseRequisition = purchaseMapper.selectByProcurementProductId(procurementProduct.getId());
                    purchaseRequisition.setRequisitionState(0);
                    purchaseMapper.updateById(purchaseRequisition);

                }
                procurementProductMapper.deleteById(procurementProduct);
            });
            customerService.deleteThorough(23,id);
            procurementMapper.deleteById(id);
        }
    }



    @Override
    public void auditProcurement(DoReminder doReminder) {
        Procurement procurement = procurementMapper.selectById(doReminder.getCorrlelationId());
        procurement.setStatus(doReminder.getStatus());
        procurement.setArrivalState(1);
        procurementMapper.updateById(procurement);
    }

    @Override
    public void receiptProduct(Procurement procurement){
        //生成入库单
        Procurement procured = procurementMapper.selectById(procurement.getId());
        procured.setArrivalState(2);
        procurementMapper.updateById(procured);
        WarehouseInout inout = new WarehouseInout();
        Warehouse warehouse = warehouseMapper.selectById(1);
        //暂时放到默认仓库
        inout.setInoutType(2);
        inout.setType(4);
        inout.setWarehouseId(1);
        inout.setClaimId(procurement.getId());
        inout.setResponsibleId(warehouse.getAdminId());
        inout.setInoutTime(DateUtil.date());
        //自动生成编号
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String code = "INOUT-" + sdf.format(DateUtil.date());
        String maxCode =  inoutMapper.maxRoundInoutNumber(code);
        String newCode = null;
        if (StrUtil.isEmpty(maxCode)){
            newCode = code + "001";
        }
        else {
            String getMaxCode = maxCode.substring(14, 17);
            newCode = code + DateNumUtils.getNum(getMaxCode);
        }
        inout.setInoutCode(newCode);
        inoutMapper.insert(inout);

        procurement.getProcurementProductList().forEach(procurementProduct -> {
            procurementProductMapper.updateById(procurementProduct);
            QueryWrapper<Stock> wrapper = new QueryWrapper<>();
            wrapper.lambda().eq(Stock::getProductSkuId,procurementProduct.getProductSpuId()).eq(Stock::getWarehouseId,1);
            Stock stock = stockMapper.selectOne(wrapper);
            InoutProduct inoutProduct = new InoutProduct();
            inoutProduct.setInoutId(inout.getId());
            inoutProduct.setClaimsProductId(procurementProduct.getProductSpuId());
            inoutProduct.setActualNum(procurementProduct.getActualNum());
            //判断产品转换率是否为空
//            if (procurementProduct.getConversionRate() != null ){
//                inoutProduct.setInoutNum(procurementProduct.getActualNum() * procurementProduct.getConversionRate());
//            } else {
//                inoutProduct.setInoutNum(procurementProduct.getActualNum());
//            }
            inoutProduct.setInoutNum(procurementProduct.getActualNum());
            //判断产品是否有库存
            if (stock != null){
                inoutProduct.setInceptionNum(stock.getQuantity());
            } else {
                inoutProduct.setInceptionNum(0.00);
            }
            //判断当前 单位id 是否为空
            if (procurementProduct.getUnitId() == null){
                Product product = productMapper.selectById(procurementProduct.getProductSpuId());
                inoutProduct.setUnitId(product.getProductUnitId());
            } else {
                inoutProduct.setUnitId(procurementProduct.getUnitId());
            }
            inoutProduct.setFinallyNum(Math.abs(inoutProduct.getInceptionNum() + inoutProduct.getInoutNum()));
            inoutProductMapper.insert(inoutProduct);
        });
    }

    @Override
    public AddPageData addCancel(Procurement procurement) {
        Procurement procured = procurementMapper.selectById(procurement.getId());
        String newTitle = procured.getTitle().concat("-" + procurement.getTitle());
        procured.setUpdateTime(DateUtil.date());
        procured.setTitle(newTitle);
        procured.setStatus(0);
        procured.setProcuredState(2);
        //procured.setArrivalState(3);
        procured.setRemark(procurement.getRemark());
        procurementMapper.updateById(procured);

        AddPageData addPageData = new AddPageData();
        addPageData.setStreamType(24);
        addPageData.setWorkflowJson(procurement.getWorkflowJsonList());
        addPageData.setTitle(procured.getTitle());
        addPageData.setAdminId(procured.getAdminId());
        addPageData.setCorrelationId(procured.getId());
        addPageData.setExempt(procurement.getExempt());
        return addPageData;
    }

    @Override
    public void cancel(Integer id) {
        Procurement procurement = procurementMapper.selectById(id);
        procurement.setUpdateTime(DateUtil.date());
        if (procurement.getStatus() != 1) {
            String title = procurement.getTitle();
            if(title.contains("-")){
                int index = title.indexOf("-");
                title = title.substring(0, index);
            }
            procurement.setTitle(title);
            procurement.setProcuredState(1);
            procurement.setArrivalState(0);
            procurementMapper.updateById(procurement);
        }
    }

    @Override
    public void antiAudit(Integer correlationId) {
        QueryWrapper<Procurement> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(Procurement::getId,correlationId).eq(Procurement::getStatus,1);
        Procurement procurement = procurementMapper.selectOne(wrapper);
        procurement.setStatus(0);
        procurementMapper.updateById(procurement);
    }

    @Override
    public Procurement detailById(Integer id) {
        Procurement procurement = procurementMapper.selectDetailById(id);
        List<ProcurementProduct> procurementProducts = procurementProductMapper.selectListByProcurementId(id);
        procurement.setProcurementProductList(procurementProducts);
        return procurement;
    }
}
